Near-linear basis set dependency handling and level shifting for RHF/UHF/DFT/UDFT#455
Near-linear basis set dependency handling and level shifting for RHF/UHF/DFT/UDFT#455vtripath65 wants to merge 39 commits intomerzlab:masterfrom
Conversation
Remove the eigen vectors of overlap matrix corresponding
low eigen function (less than 1E-05) while forming S^{-1/2}
The debug prints are removed and thresholds are returned to original values. Arrays are properly allocated to avoid multiple reallocation and memory leak.
…lication and diagonalization
In the symmetric orthogonalization case (NBSuse == nbasis), oeff is not allocated, but the SCF DIIS procedure (electdiis) was writing to it in step 8 and the level-shift block, causing a segfault. - Step 8 transform: route the X^T.(O.X) result into o instead of oeff when NBSuse == nbasis; correct the leading dimension from NBSuse to nbasis to match o's declared shape - Level-shift block: split into canonical/symmetric branches so each operates on its own matrix (oeff vs o) - MAT_DIAG call: conditionally diagonalize oeff or o depending on the orthogonalization path - Ring-buffer, B-matrix, and C=XC' steps likewise split into canonical/symmetric branches, reusing hold2/hold instead of hold4/hold5 - Remove unused itererror staging array and hold5 scratch array - Fix sign of DGEMM 4 (alpha=-1, beta=1) to correctly accumulate e(i) = ODS - SDO without a separate subtraction loop - Add NBSuse declaration to allocate_quick_qm_struct in quick_calculated_module.f90
|
Currently, CUDA tests stop when running a test that requires f functions and the code was not compiled with f functions. This is also the case with the current master (6369ecd). I am investigating. |
agoetz
left a comment
There was a problem hiding this comment.
This looks great. I think we need to fix minor things and Mulliken charges for two tests seem off, please see comments I made for source code lines.
|
|
||
| ! basis set number | ||
| integer, pointer:: nbasis | ||
| integer, pointer:: NBSuse |
There was a problem hiding this comment.
For some reason quick_molspec%NBSuse does not really seem to be used.
| enddo | ||
| enddo | ||
| quick_qm_struct%s(Jbas,Ibas) = SJI | ||
| ! do not consider small overlap matrix elements |
There was a problem hiding this comment.
What is the reason for not considering small overlap matrix elements?
There was a problem hiding this comment.
I printed the overlap matrix elements in Gaussian and they were ignoring the small overlap matrix elements. I was experimenting with this to check if we are introducing unnecesdsary noise. I added this during my benzene aug-cc-pvdz tests which I never managed to converge with OVCUT=1.0e-6. We can remove this. Does not affect anything I think.
There was a problem hiding this comment.
OK. If it does not improve convergence then we should not touch the matrix elements. I am trying to think where this could be useful or have an effect - the only thing that comes to mind is sparse matrix operations in linear scaling models. We could leave it in the code but set the default OVCUT to zero.
| COEFF = 0.0d0 | ||
| RHS = 0.0d0 | ||
| allerror = 0.0d0 | ||
| if(allocated(allerror)) allerror = 0.0d0 |
There was a problem hiding this comment.
Isn't allerror always allocated, which makes this if check superfluous?
| call MAT_DGEMM ('t', 'n', NBSuse, NBSuse, NBSuse, 1.0d0, quick_qm_struct%oldvec, & | ||
| NBSuse, quick_scratch%hold2, NBSuse, 0.0d0, quick_qm_struct%o, NBSuse) | ||
|
|
||
| homo = quick_molspec%nelec/2 |
There was a problem hiding this comment.
This code here is independent of dimension of NBSuse vs nbasis. Should be moved out of the if block
| ! Standard case (NBSuse == nbasis): diagonalize o(nbasis,nbasis) in place. | ||
| RECORD_TIME(timer_begin%TDiag) | ||
|
|
||
| if(NBSuse .ne. nbasis) then |
There was a problem hiding this comment.
This is where pointers can become useful. If we set
if (NBSuse .ne. nbasis) then
operator => quick_qm_struct%oeff
else
operator => quick_qm_struct%o
end if
then we don't need the if statement here, and probably also not in other places.
|
|
||
| ! Near-linear dependency: use hold4(NBSuse,NBSuse) as intermediate. | ||
| ! Standard case: use hold2(nbasis,nbasis) as intermediate. | ||
| if(idiis .ge. quick_method%LShift_cycle .and. errormax .gt. quick_method%LShift_err)then |
Summary
This PR adds robust handling of near-linear basis set dependencies and level shifting to QUICK's SCF and USCF solvers, and fixes several related correctness and stability issues.
Near-linear dependency (canonical orthogonalization)
When the smallest eigenvalue of the overlap matrix falls below the
OVCUTthreshold (default 1e-5), QUICK now detects the near-linear dependency infullxand setsNBSuse < nbasis. The transformation matrixxis then rectangular(nbasis × NBSuse)rather than square.All downstream SCF operations are updated to respect this reduced dimension:
quick_overlap_module:fullxnow detects near-linear dependency by scanning overlap eigenvalues againstOVCUT, logs the number of linearly independent functions, condition number, and smallest eigenvalue, and builds a rectangularx(nbasis, NBSuse)viatmpU(nbasis, NBSuse)andtmpS(NBSuse, NBSuse)scratch arrays.quick_scf_module(RHF/DFT): DIIS error vectors stored asallerror(NBSuse, NBSuse, maxdiis); DIIS transformations usehold3(nbasis, NBSuse)andhold4(NBSuse, NBSuse)rectangular intermediates; diagonalization, level shifting, and MO back-transform all operate in theNBSuse-dimensional subspace. MPI broadcasts use the correctnbasis × NBSuseandNBSusesizes forcoandE.quick_uscf_module(UHF/UDFT): All of the above applied independently to alpha and beta spins; MPI broadcasts corrected forco/cob(nbasis × NBSuse) andE/Eb(NBSuse).New data fields in
quick_qm_struct_typeoeff(NBSuse, NBSuse)— reduced-space alpha Fock matrix for diagonalization and level shiftingoeffb(NBSuse, NBSuse)— same for beta spin (UHF/UDFT)oldvec(NBSuse, NBSuse)— alpha MO coefficient matrix in the reduced space, used to apply the level shift from the previous iterationoldvecb(NBSuse, NBSuse)— same for beta spin (UHF/UDFT)co(nbasis, NBSuse)andcob(nbasis, NBSuse)— alpha/beta MO coefficient matrices resized from(nbasis, nbasis)to(nbasis, NBSuse)E(NBSuse)andEb(NBSuse)— orbital energy vectors resized fromnbasistoNBSuseA new
allocate_quick_qm_struct_fullxsubroutine allocates all dimension-dependent fields (called fromfullxafterNBSuseis determined).Level shifting
Level shifting is applied to improve convergence of difficult cases. Three new keywords control the behavior (all can be set in the input file):
LSHIFT_CYCLELSHIFT_ERRLSHIFT_GAPFor UHF/UDFT, alpha and beta shifts are applied independently based on their respective HOMO indices (
nelecandnelecb).Overlap matrix cutoffs
OVCUT(default 1e-5): eigenvalue threshold for near-linear dependency detection.ovmatelems(default 1e-6): elements of the overlap matrix smaller than this value are set to zero before diagonalization.New regression tests
Four new tests covering near-linear dependency cases (all have
NBSuse < nbasis):ene_benzene_b3lyp_aug-cc-pvdzene_benzene_ub3lyp_aug-cc-pvdzene_caffeine_b3lyp_631+gdene_caffeine_ub3lyp_631+gdCloses #436.